C.S.Burner 🪙 ━►🔥GIT Node
Node / reticulum_mirror / MeshChatX / files / meshchatx / src / frontend / components / tools / ManagementIdentityPicker.vue
Displaying Raw • Download
meshchatx/src/frontend/components/tools/ManagementIdentityPicker.vue 65ca9ddc823fcc2c8f8653c553b944b85db0875f (65ca9ddc) Text, 4.94 KB
T8b949e<!-- SPDX-License-Identifier: 0BSD -->
Tff7b72<templateTff7b72>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffspace-y-2Ta5d6ff"Tff7b72>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffflex flex-wrap items-end gap-2Ta5d6ff"Tff7b72>
Tff7b72<label Te6edf3class=Ta5d6ff"Ta5d6ffblock min-w-0 flex-1 space-y-1Ta5d6ff"Tff7b72>
Tff7b72<span Te6edf3class=Ta5d6ff"Ta5d6fftext-xs font-medium text-gray-700 dark:text-zinc-300Ta5d6ff"Tff7b72>{{
Te6edf3$t("remote_mgmt.management_identity")
}}Tff7b72</span>
Tff7b72<select
Te6edf3:value=Ta5d6ff"Ta5d6ffmodelValueTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffinput-field w-full font-mono text-xsTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffdisabled || loadingTa5d6ff"
@Te6edf3change=Ta5d6ff"Ta5d6ffonSelect(Te6edf3$event.target.valueTa5d6ff)Ta5d6ff"
Tff7b72>
Tff7b72<option Te6edf3value=Ta5d6ff"Ta5d6ff"Tff7b72>{{ Te6edf3$t("remote_mgmt.select_identity") }}Tff7b72</option>
Tff7b72<option Te6edf3v-for=Ta5d6ff"Ta5d6ffitem in identitiesTa5d6ff" Te6edf3:key=Ta5d6ff"Ta5d6ffitem.pathTa5d6ff" Te6edf3:value=Ta5d6ff"Ta5d6ffitem.pathTa5d6ff"Tff7b72>
{{ item.name }} ({{ shortHash(item.hash) }})
Tff7b72</option>
Tff7b72</select>
Tff7b72</label>
Tff7b72<button
Te6edf3type=Ta5d6ff"Ta5d6ffbuttonTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffsecondary-chip px-3 py-2 text-xsTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffdisabled || loadingTa5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffloadIdentitiesTa5d6ff"
Tff7b72>
Tff7b72<MaterialDesignIcon Te6edf3icon-name=Ta5d6ff"Ta5d6ffrefreshTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffsize-4Ta5d6ff" Tff7b72/>
Tff7b72</button>
Tff7b72<button
Te6edf3type=Ta5d6ff"Ta5d6ffbuttonTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffsecondary-chip px-3 py-2 text-xsTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffdisabled || creatingTa5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffcreateIdentityTa5d6ff"
Tff7b72>
Tff7b72<MaterialDesignIcon Te6edf3icon-name=Ta5d6ff"Ta5d6ffplusTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffsize-4Ta5d6ff" Tff7b72/>
{{ Te6edf3$t("remote_mgmt.create_identity") }}
Tff7b72</button>
Tff7b72</div>
Tff7b72<p Te6edf3v-if=Ta5d6ff"Ta5d6ffselectedHashTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6fffont-mono text-[10px] text-gray-500 dark:text-zinc-500 break-allTa5d6ff"Tff7b72>
{{ selectedHash }}
Tff7b72</p>
Tff7b72</div>
Tff7b72</template>
Tff7b72<scriptTff7b72>
import MaterialDesignIcon from "../MaterialDesignIcon.vue";
import ToastUtils from "../../js/ToastUtils";
export default {
name: "ManagementIdentityPicker",
components: { MaterialDesignIcon },
props: {
modelValue: { type: String, default: "" },
disabled: { type: Boolean, default: false },
defaultName: { type: String, default: "mgmt" },
},
emits: ["update:modelValue", "update:identityHash", "loaded"],
data() {
return {
identities: [],
loading: false,
creating: false,
};
},
computed: {
selectedHash() {
const match = this.identities.find((item) => item.path === this.modelValue);
return match?.hash || "";
},
},
watch: {
selectedHash(value) {
this.$emit("update:identityHash", value || "");
},
},
async mounted() {
await this.loadIdentities();
},
methods: {
shortHash(hash) {
if (!hash || hash.length Tff7b72< 10) return hash || "";
return `${hash.slice(0, 8)}…`;
},
onSelect(value) {
this.$emit("update:modelValue", value || "");
},
async loadIdentities() {
Te6edf3this.loading = Ta5d6fftrue;
try {
const Te6edf3response = Ta5d6ffawait window.api.get("/api/v1/reticulum/management-identities");
Te6edf3this.identities = Ta5d6ffArray.isArray(response.data?.identities) ? response.data.identities : [];
this.$emit("loaded", this.identities);
if (this.modelValue && !this.identities.some((item) =Tff7b72> item.path === this.modelValue)) {
this.$emit("update:modelValue", "");
}
} catch (error) {
ToastUtils.error(error?.response?.data?.message || this.$t("remote_mgmt.failed_load_identities"));
} finally {
this.loading = false;
}
},
async createIdentity() {
const suggested = this.defaultName || "mgmt";
const name =
typeof window !== "undefined" && window.prompt
? window.prompt(this.$t("remote_mgmt.create_identity_prompt"), suggested)
: suggested;
if (!name || !String(name).trim()) {
return;
}
this.creating = true;
try {
const response = await window.api.post("/api/v1/reticulum/management-identities", {
name: String(name).trim(),
});
const identity = response.data?.identity;
await this.loadIdentities();
if (identity?.path) {
this.$emit("update:modelValue", identity.path);
}
ToastUtils.success(this.$t("remote_mgmt.identity_created"));
} catch (error) {
ToastUtils.error(error?.response?.data?.message || this.$t("remote_mgmt.failed_create_identity"));
} finally {
this.creating = false;
}
},
},
};
Tff7b72</script>
Served by rngit 1.5.2 - Generated in 0.04s